import java.util.*;

/**
 * This class processes the symbol table
 * into a grid or index presentation in LaTeX.
 * 
 * @author James Stanier
 */
public class GridOutput {

	ArrayList<Env> symbolTable;
	ArrayList<SymbolLineNo> outputOrder;
	Stack<Env> scopeStack;
	String output;
	String fileName;

	/**
	 * Constructor.
	 * @param t The symbol table.
	 * @param s The input file name.
	 */
	public GridOutput(ArrayList<Env> t, String s) {
		symbolTable = t;
		outputOrder = new ArrayList<SymbolLineNo>();
		scopeStack = new Stack<Env>();
		fileName = s;
	}

	/**
	 * Arranges all input files by line number.
	 */
	public void arrangeOutputByLineNo() {
		int i = 0;
		while(symbolTable.size() > 0) {
			if(i >= symbolTable.size()) {
				break;
			}
			Env x = symbolTable.get(i);
			ArrayList<String> symbols = x.getSymbols();

			for(int j = 0; j < symbols.size(); j++) {
				Symbol s = x.getTable().get(symbols.get(j));
				SymbolLineNo t = new SymbolLineNo(s.getLabel(), s.getID(), s.getType(), s.getLineNumber());
				outputOrder.add(t);
			}
			i++;
		}
		Collections.sort(outputOrder);
	}

	/**
	 * Generate a grid presentation of the variables.
	 * @return Formatted grid LaTeX code.
	 */
	public String generateGrid() {

		// Trim name from absolute path
		String longFileName = JavaParser.getFileName();
		int counter = 0;
		char c = System.getProperty("file.separator").toCharArray()[0];
		for(int j = longFileName.length()-1; j >=0; j--) {
			counter = j;
			if(longFileName.charAt(j) == c) {
				break;
			}
		}

		longFileName = longFileName.substring(counter+1);

		output = "\\pagebreak\\subsection{Variable grid for \\textsf{" + longFileName + "}}\n" +
		"Every identifer used in the program appears here in this section, along " +
		"with the line number upon which it was declared." + "\\" + "\\" + "\n";

		output += "\\begin{center}\n" +
		"\\begin{longtable}{|c|c|c|}\n" +
		"\\hline\n" + "\\textbf{Type} & \\textbf{Name} & \\textbf{Line number} \\" +
		"\\" + "\n\\hline\n";

		for(int i = 0; i < outputOrder.size(); i++) {

			Symbol x = outputOrder.get(i);

			if(x.getLabel().contains("_")) {
				x.setLabel(x.getLabel().replace("_", "\\_"));
			}
			if(x.getLabel().contains("<")) {
				x.setLabel(x.getLabel().replace("<", "$<$"));
			}
			if(x.getLabel().contains(">")) {
				x.setLabel(x.getLabel().replace("<", "$>$"));
			}

			if(x.getType().contains("_")) {
				x.setType(x.getType().replace("_", "\\_"));
			}
			if(x.getType().contains("<")) {
				x.setType(x.getType().replace("<", "$<$"));
			}
			if(x.getType().contains(">")) {
				x.setType(x.getType().replace(">", "$>$"));
			}

			output += x.getType() + " & " + x.getLabel() + " & " + x.getLineNumber() +
			" \\" + "\\\n" + "\\hline\n";
		}

		output += "\\end{longtable}\n\\end{center}";

		return output;
	}

	/**
	 * Generate a regular array of variable names.
	 * @return
	 */
	public ArrayList<String> generateStringArray() {
		ArrayList<String> outputArray = new ArrayList<String>();

		for(int i = 0; i < symbolTable.size(); i++) {
			Env e = symbolTable.get(i);
			ArrayList<String> symbols = e.getSymbols();

			for(int j = 0; j < symbols.size(); j++) {
				Symbol s = e.getTable().get(symbols.get(j));
				outputArray.add(s.getLabel());
			}
		}
		return outputArray;
	}

	/**
	 * Generate an index format presentation of variables
	 * in LaTeX code.
	 * @return Index presentation of variables in LaTeX.
	 */
	public String generateIndex() {

		// Trim name from absolute path
		String longFileName = JavaParser.getFileName();
		int counter = 0;
		char c = System.getProperty("file.separator").toCharArray()[0];
		for(int j = longFileName.length()-1; j >=0; j--) {
			counter = j;
			if(longFileName.charAt(j) == c) {
				break;
			}
		}

		longFileName = longFileName.substring(counter+1);

		output = "\\pagebreak\\subsection{Variable index for \\textsf{" + longFileName + "}}\n" +
		"Every identifer used in the program appears here in this section, along " +
		"with the line number upon which it was declared." + "\\" + "\\" + "\\" + "\\" + "\n";

		ArrayList<Symbol> outputArray = new ArrayList<Symbol>();

		for(int j = 0; j < outputOrder.size(); j++) {
			SymbolLineNo s = outputOrder.get(j);

			if(s.getLabel().contains("_")) {
				s.setLabel(s.getLabel().replace("_", "\\_"));
			}
			if(s.getLabel().contains("<")) {
				s.setLabel(s.getLabel().replace("<", "$<$"));
			}
			if(s.getLabel().contains(">")) {
				s.setLabel(s.getLabel().replace("<", "$>$"));
			}

			if(s.getType().contains("_")) {
				s.setType(s.getType().replace("_", "\\_"));
			}
			if(s.getType().contains("<")) {
				s.setType(s.getType().replace("<", "$<$"));
			}
			if(s.getType().contains(">")) {
				s.setType(s.getType().replace(">", "$>$"));
			}

			Symbol t = new Symbol(s.getLabel(), s.getID(), s.getType(), s.getLineNumber());
			outputArray.add(t);
		}

		Collections.sort(outputArray);
		
		for(int i = 0; i < outputArray.size(); i++) {
			Symbol s = outputArray.get(i);
			output += "\\textbf{" + s.getLabel() + "}, \\textit{" + s.getType() +
			"}, " + s.getLineNumber() + ".\\\\\n";
		}
		return output;
	}

}
